/*
 * Copyright (c) 2018-2999 九五云信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.service.WxPayService;
import com.yami.shop.bean.app.param.PayParam;
import com.yami.shop.bean.enums.OrderStatus;
import com.yami.shop.bean.enums.OrderType;
import com.yami.shop.bean.event.CheckGroupOrderEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.bean.event.CheckSecKillOrderEvent;
import com.yami.shop.common.config.Constant;
import com.yami.shop.common.enums.PayType;
import com.yami.shop.bean.event.PaySuccessOrderEvent;
import com.yami.shop.bean.pay.PayInfoDto;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.config.WxConfig;
import com.yami.shop.dao.OrderMapper;
import com.yami.shop.dao.OrderSettlementMapper;
import com.yami.shop.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lgh on 2018/09/15.
 */
@Slf4j
@Service
@AllArgsConstructor
public class PayServiceImpl implements PayService {

    private final OrderMapper orderMapper;
    private final OrderSettlementMapper orderSettlementMapper;
    private final ApplicationContext applicationContext;
    private final ApplicationEventPublisher eventPublisher;
    private final WxConfig wxConfig;
    private final NotifyTemplateService notifyTemplateService;
    private final Snowflake snowflake;

    /**
     * 不同的订单号，同一个支付流水号
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PayInfoDto pay(String userId, PayParam payParam) {
        // 支付单号
        String payNo = String.valueOf(snowflake.nextId());
        String[] orderNumbers = payParam.getOrderNumbers().split(StrUtil.COMMA);
        // 应支付的总金额
        double payAmount = 0.0;
        double payScore = 0;
        int isScore = 0;
        // 修改订单信息
        for (String orderNumber : orderNumbers) {
            OrderSettlement orderSettlement = orderSettlementMapper.selectOne(
                    new LambdaQueryWrapper<OrderSettlement>()
                            .eq(OrderSettlement::getUserId,userId)
                            .eq(OrderSettlement::getOrderNumber,orderNumber)
            );
            if (Objects.equals(orderSettlement.getPayStatus(), 1)) {
                // 支付失败，订单不在未支付状态
                throw new YamiShopBindException("yami.order.pay.fail");
            }
            Order order = orderMapper.getOrderByOrderNumber(orderNumber);
            if (!Objects.equals(order.getStatus(), OrderStatus.UNPAY.value())) {
                // 支付失败，订单不在未支付状态
                throw new YamiShopBindException("yami.order.pay.fail");
            }
            order.setPayType(payParam.getPayType());
            orderMapper.updateById(order);


            orderSettlement.setPayNo(payNo);
            orderSettlement.setPayType(payParam.getPayType());
            orderSettlement.setUserId(userId);
            orderSettlement.setOrderNumber(orderNumber);
            payAmount = Arith.add(payAmount, orderSettlement.getPayAmount());
            payScore += orderSettlement.getPayScore() == null ? 0:orderSettlement.getPayScore();
            orderSettlementMapper.updateByOrderNumberAndUserId(orderSettlement);
            // 普通订单创建时间经过限定订单超时分钟，如果为true则早于当前时间表示过期，抛出异常
            if(!DateUtil.isExpired(order.getCreateTime(), DateField.MINUTE, Constant.ORDER_MAX_TIME, new Date())){
                // 秒杀订单已经过期，无法进行支付
                throw new YamiShopBindException("yami.order.expired");
            }
            // 如果是秒杀订单,还需判断秒杀订单有没有过期
            if(Objects.equals(order.getOrderType(),OrderType.SECKILL.value())){
                applicationContext.publishEvent(new CheckSecKillOrderEvent(order));
            }
            // 如果是团购订单,还需判断团购订单有没有过期
            if(Objects.equals(order.getOrderType(),OrderType.GROUP.value())){
                applicationContext.publishEvent(new CheckGroupOrderEvent(order));
            }
        }
        //如果金额小于0.01 支付积分大于0则为纯积分支付
        if(payAmount < 0.01 && payScore > 0){
            isScore = 1;
            paySuccess(payNo, null, PayType.SCOREPAY.value());
        }
        PayInfoDto payInfoDto = new PayInfoDto();
        payInfoDto.setBody("商城订单");
        payInfoDto.setPayAmount(payAmount);
        payInfoDto.setPayNo(payNo);
        payInfoDto.setIsScore(isScore);
        return payInfoDto;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Order> paySuccess(String payNo, String bizPayNo,Integer payType) {
        List<OrderSettlement> orderSettlements = orderSettlementMapper.selectList(new LambdaQueryWrapper<OrderSettlement>().eq(OrderSettlement::getPayNo, payNo));
        OrderSettlement settlement = orderSettlements.get(0);
        List<String> orderNumbers = orderSettlements.stream().map(OrderSettlement::getOrderNumber).collect(Collectors.toList());
        // 订单已支付
        if (settlement.getPayStatus() == 1) {
            log.info("订单已支付，settlement.id：{}", settlement.getSettlementId());
            return Collections.emptyList();
        }
        // 修改订单结算信息
        if (orderSettlementMapper.updateToPay(payNo,bizPayNo, settlement.getVersion()) < 1) {
            // 结算信息已更改
            throw new YamiShopBindException("yami.modified.settlement.information");
        }
        // 将订单改为已支付状态
        orderMapper.updateByToPaySuccess(orderNumbers, payType);

        List<OrderItem> allOrderItem = new ArrayList<>();

        List<Order> orders = orderNumbers.stream().map(orderNumber -> {
            Order order = orderMapper.getOrderAndOrderItemByOrderNumber(orderNumber);
            allOrderItem.addAll(order.getOrderItems());
            return order;
        }).collect(Collectors.toList());

        // 消息推送-支付成功
        notifyTemplateService.sendNotifyOfPaySuccess(orders);

        //如果是积分订单无需改变,不是则发送支付成功事件
        if(!Objects.equals(orders.get(0).getOrderType(), OrderType.SCORE.value())){
//            OrderSettlement orderSettlement = orderSettlements.get(0);
//            Order order = orders.get(0);
//            eventPublisher.publishEvent(new UpdateUserScoreEvent(ScoreLogType.SCORE_CASH.value(),orderSettlement.getPayScore(),0,
//                    order.getOrderNumber(), "购买商品花费的积分",order.getUserId()));
//        }else {
            eventPublisher.publishEvent(new PaySuccessOrderEvent(orders, allOrderItem, payNo));
        }
        return orders;
    }


}
